package com.ttk.issuetracker.service;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ttk.issuetracker.dao.TaskDao;
import com.ttk.issuetracker.dao.TaskLogDao;
import com.ttk.issuetracker.model.Task;
import com.ttk.issuetracker.model.TaskLog;
import com.ttk.issuetracker.model.User;
import com.ttk.issuetracker.vo.Result;
import com.ttk.issuetracker.vo.ResultFactory;

@Transactional
@Service("taskLogService")
public class TaskLogServiceImpl extends AbstractService implements
		TaskLogService {

	@Autowired
	protected TaskLogDao taskLogDao;
	@Autowired
	protected TaskDao taskDao;

	public TaskLogServiceImpl() {
		super();
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	@Override
	public Result<TaskLog> store(Integer idTaskLog, Integer idTask,
			String username, String taskDescription, Date taskLogDate,
			int taskMinutes, String actionUsername) {
		if (!isValidUser(actionUsername)) {
			return ResultFactory.getFailResult(USER_INVALID);
		}

		TaskLog taskLog;
		if (idTaskLog != null) {
			taskLog = new TaskLog();
		} else {
			taskLog = taskLogDao.find(idTaskLog);
			if (taskLog == null) {
				return ResultFactory
						.getFailResult("Unable find task log with taskLogId ["
								+ idTaskLog + "]");
			}
		}

		User user = null;
		if (username != null) {
			user = userDao.findByUsername(username);
			if (user == null) {
				return ResultFactory
						.getFailResult("Unable find user log with userName ["
								+ username + "]");
			}
		}

		taskLog.setTaskDescription(taskDescription);
		taskLog.setTaskLogDate(taskLogDate);
		taskLog.setTaskMinutes(taskMinutes);
		taskLog.setUser(user);

		Task task = null;
		if (idTask != null) {
			task = taskDao.find(idTask);
			if (task == null) {
				return ResultFactory
						.getFailResult("Unable find task log with idTask ["
								+ idTask + "]");
			}
		}

		if (!task.equals(taskLog.getTask())) {
			// create new case
			if (taskLog.getId() == null) {
				taskLog.setTask(task);
				task.getTaskLogs().add(taskLog);
			} else {// merge case
				taskLog.getTask().removeTaskLog(taskLog);
				taskLog.setTask(task);
				task.getTaskLogs().add(taskLog);
			}
		}

		if (taskLog.getId() == null) {
			taskLogDao.persist(taskLog);
		} else {
			taskLog = taskLogDao.merge(taskLog);
		}

		return ResultFactory.getSuccessResult(taskLog);
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	@Override
	public Result<TaskLog> remove(Integer idTaskLog, String actionUsername) {
		User actionUser = userDao.findByUsername(actionUsername);
		if (actionUser == null) {
			return ResultFactory.getFailResult(USER_INVALID);
		}

		if (idTaskLog == null) {
			return ResultFactory
					.getFailResult("Unable to remove TaskLog [null idTaskLog]");
		}

		TaskLog taskLog = taskLogDao.find(idTaskLog);
		if (taskLog == null) {
			return ResultFactory
					.getFailResult("Unable to load TaskLog for removal with idTaskLog = "
							+ idTaskLog);
		}

		// only the user that owns the task log may remove it
		// OR an admin user
		if (actionUser.isAdmin() || taskLog.getUser().equals(actionUser)) {
			Task task = taskLog.getTask();
			if (task != null) {
				task.getTaskLogs().remove(taskLog);
			}
			taskLogDao.remove(taskLog);
			return ResultFactory
					.getSuccessResultMsg("taskLog removed successfully");
		} else {
			return ResultFactory
					.getFailResult("Only an admin user or task log owner can delete a task log");
		}
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	@Override
	public Result<TaskLog> find(Integer idTaskLog, String actionUsername) {
		User actionUser = userDao.findByUsername(actionUsername);
		if(actionUser == null) {
			return ResultFactory.getFailResult(USER_INVALID);
		}
		if(idTaskLog == null) {
			return ResultFactory.getFailResult("Unable get TaskLog with idTaskLog is null");
		}
		TaskLog taskLog = taskLogDao.find(idTaskLog);
		if(taskLog == null){
			return ResultFactory.getFailResult("Task log not found with idTaskLog=" + idTaskLog);
		} else if( actionUser.isAdmin() || taskLog.getUser().equals(actionUser)) {
			return ResultFactory.getSuccessResult(taskLog);
		} else {
			return ResultFactory.getFailResult("User does not have permission to view this task log");
		}
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	@Override
	public Result<List<TaskLog>> findByUser(String username, Date startDate,
			Date endDate, String actionUsername) {
		User taskUser = userDao.findByUsername(username);
		User actionUser = userDao.findByUsername(actionUsername);
		if (taskUser == null || actionUser == null) {
			return ResultFactory.getFailResult(USER_INVALID);
		}
		if (startDate == null || endDate == null) {
			return ResultFactory
					.getFailResult("Start and end date are required for findByUser ");
		}
		if (actionUser.isAdmin() || taskUser.equals(actionUser)) {
			return ResultFactory.getSuccessResult(taskLogDao.findByUser(
					taskUser, startDate, endDate));
		} else {
			return ResultFactory
					.getFailResult("Unable to find task logs. User does not have permission with username="	+ username);
		}
	}
}
